package com.gitee.huanminabc.fastboot.load.stage.syncstage;

import com.gitee.huanminabc.jcommon.container.ContainerCreate;
import com.gitee.huanminabc.jcommon.container.ListSlice;
import com.gitee.huanminabc.jcommon.reflect.AnnotationUtil;
import com.gitee.huanminabc.jcommon.reflect.ClassMatcher;
import com.gitee.huanminabc.jcommon.reflect.ClassUtil;
import com.gitee.huanminabc.jcommon.reflect.MethodUtil;
import com.gitee.huanminabc.fastboot.annotation.Aop;
import com.gitee.huanminabc.fastboot.context.AppContext;
import com.gitee.huanminabc.fastboot.context.AppContextUtil;
import com.gitee.huanminabc.fastboot.proxy.ByteBuddyProxy;
import com.gitee.huanminabc.fastboot.proxy.InterceptorHandle;
import lombok.extern.slf4j.Slf4j;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * 简要描述: AOP类加载阶段,必须在类加载阶段之后,容器加载阶段之前
 * @Author: huanmin
 * @Date: 2025/4/3 00:11
 * @Version: 1.0
 * @Description: 文件作用详细描述....
 */
@Slf4j
public class ClassLoadContainerAopChildStage{
    private final Map<Class<?>, Set<Method>> classMethodProxyMap = new ConcurrentHashMap<>();
    private final Map<Method, InterceptorHandle> methodInterceptorHandleMap = new ConcurrentHashMap<>();



    public  boolean isAopClass(Class<?> zclass)  {
       return classMethodProxyMap.get(zclass) != null;
    }

    public  void createAopProxy() {
        //扫描所有的AOP需要代理的类
        AppContext.allAopInterceptorHandleClasses.forEach(this::scanAopClass);
        //然后根据扫描的情况创建代理
        //这个耗时在400左右, ByteBuddy第一次的内部在预加载一些内容导致的, 这个已经做了预加载了在 AppInteriorConfigLoadStage里面
        classMethodProxyMap.entrySet().parallelStream().forEach(entry -> {
            Class<?> clazz = entry.getKey();
            Set<Method> methods = entry.getValue();
            Map<Method, InterceptorHandle> interceptorHandleMap = new HashMap<>();
            Method[] methodArray = methods.toArray(new Method[0]);
            for (Method method : methodArray) {
                InterceptorHandle interceptorHandle = methodInterceptorHandleMap.get(method);
                if (interceptorHandle != null) {
                    interceptorHandleMap.put(method, interceptorHandle);
                }
            }
            Object proxy = ByteBuddyProxy.createProxy(clazz,interceptorHandleMap);
            AppContextUtil.addAppContainer(clazz,proxy);
        });
    }

    //清理
    public  void clear() {
        classMethodProxyMap.clear();
        methodInterceptorHandleMap.clear();
    }


    private  void scanAopClass(Class<?> zclass)  {
        Aop annotation = zclass.getAnnotation(Aop.class);
        InterceptorHandle interceptorHandle = (InterceptorHandle)ClassUtil.newInstance(zclass);
        Class<? extends Annotation> valueAnno = annotation.value();
        String[] matchClass = annotation.match();
        if (annotation.value() != null) {
            for (String rule : matchClass) {
                scanMatchClassProxy(interceptorHandle,rule);
            }
        }
        Class<? extends Annotation>[] annos = annotation.note();
        List<Class<? extends Annotation>> annotationList=  new ArrayList<>(Arrays.asList(annos));
        annotationList.add(valueAnno);
        //需要扫描的注解,类和方法上都需要
        Set<Class<? extends Annotation>> newAnnotationList = annotationList.stream().filter(Objects::nonNull).collect(Collectors.toSet());
        if (!newAnnotationList.isEmpty()){
            scanAnnoListProxy(interceptorHandle,newAnnotationList);
        }
    }

    private  void  scanMatchClassProxy(InterceptorHandle interceptorHandle, String rule)  {
        List<Class<?>> classes = new ArrayList<>(AppContext.allClasses);
        List<Method> matchAll = ClassMatcher.match(classes, rule);
        List<List<Method>> partition = ListSlice.slice(matchAll, 1000);
        partition.parallelStream().forEach(list -> {
            for (Method method : list) {
                methodInterceptorHandleMap.put(method, interceptorHandle);
                Class<?> declaringClass = method.getDeclaringClass();
                classMethodProxyMap.computeIfAbsent(declaringClass, k -> new HashSet<>()).add(method);;
            }
        });

    }
    private  void  scanAnnoListProxy(InterceptorHandle interceptorHandle, Set<Class<? extends Annotation>> annontationList)  {
        List<Class<?>> classes = new ArrayList<>(AppContext.allClasses);
        List<List<Class<?>>> partition = ListSlice.slice(classes, 100);
        partition.parallelStream().forEach(list -> {
            list.parallelStream().forEach(aClass -> {
                scanAnnoListProxy0(interceptorHandle, annontationList, aClass);
            });
        });
    }

    private void scanAnnoListProxy0(InterceptorHandle interceptorHandle, Set<Class<? extends Annotation>> annontationList, Class<?> aClass) {
        //全类的可代理的方法
        Method[] allPublicMethods = MethodUtil.getAllPublicMethods(aClass);
        Annotation[] aClassAnnotations = aClass.getAnnotations();
        List<Annotation> includeAnnotationList = AnnotationUtil.getIncludeAnnotationList(annontationList, aClassAnnotations);
        //类上存在,那么就是代理全部
        if (!includeAnnotationList.isEmpty()) {
            //注册方法的代理
            for (Method allPublicMethod : allPublicMethods) {
                methodInterceptorHandleMap.put(allPublicMethod, interceptorHandle);
            }
            classMethodProxyMap.put(aClass, ContainerCreate.newSetList(allPublicMethods));
            return;
        }
        //如果类上没有符合的注解,那么就是方法上可能存在
        for (Method method : allPublicMethods) {
            Annotation[] methodAnnotations = method.getAnnotations();
            List<Annotation> includeAnnotationList1 = AnnotationUtil.getIncludeAnnotationList(annontationList, methodAnnotations);
            if (!includeAnnotationList1.isEmpty()) {
                //注册方法的代理
                methodInterceptorHandleMap.put(method, interceptorHandle);
                classMethodProxyMap.computeIfAbsent(aClass, k -> new HashSet<>()).add(method);
            }
        }
    }

}
